package org.zanateh.wargame.game.piece;

import java.util.ArrayList;
import java.util.List;

import org.zanateh.wargame.game.Player;
import org.zanateh.wargame.game.events.IMoveRejectedEventListener;
import org.zanateh.wargame.game.events.MoveRejectedEvent;
import org.zanateh.wargame.game.hexagon.Hexagon;
import org.zanateh.wargame.game.moveevaluators.IMoveEvaluator;
import org.zanateh.wargame.graphics.PieceDrawable;

public class Piece implements IHexagonOccupant {

	private Hexagon mCurrentHex = null;
	private PieceDrawable mPieceDrawable = null;
	private List<IMoveEvaluator> mMoveEvaluator = new ArrayList<IMoveEvaluator>();
	
	private Player mOwner;
	
	public Piece() {
		mOwner = null;
	}
	
	public Piece(Player owner) {
		mOwner = owner;
	}
	
	public Player getOwner() {
		return mOwner;
	}
	
	/*
	 * Directly sets the piece's hexagon. Meant for setup.
	 */
	public void setHex(Hexagon hex) {
		if(mCurrentHex != null) {
			mCurrentHex.removeOccupant(this);
		}
		
		mCurrentHex = hex;
		if(mCurrentHex != null ) {
			mCurrentHex.addOccupant(this);
		}

		updateDrawable();
	}
	
	public Hexagon getHex() {
		return mCurrentHex;
	}

	private void updateDrawable() 
	{
		if( mCurrentHex != null && mCurrentHex.hasDrawable()) {
			if( mPieceDrawable == null ) mPieceDrawable = new PieceDrawable(this);
			mPieceDrawable.attachToHexagon(mCurrentHex);
		}
	}

	/*
	 * Attempts to move the piece to another hexagon.
	 */
	public void moveTo(Hexagon hexagon) {
		boolean moveAllowed = true;
		String rejectedReason = null;
		for(IMoveEvaluator e : mMoveEvaluator) {
			if( ! e.allowMove(hexagon) ) {
				moveAllowed = false;
				rejectedReason = e.getRejectedMessage();
				break;
			}
		}
		
		if(moveAllowed) {
			// move allowed by own hex. What about occupants of target hex?
			
			for( IHexagonOccupant occupant : hexagon.getOccupants()) {
				if( Piece.class.isInstance(occupant)) {
					Piece occupantPiece = (Piece)occupant;
					for( IMoveEvaluator e : occupantPiece.mMoveEvaluator) {
						if( ! e.allowAnotherPieceMove(this)) {
							moveAllowed = false;
							rejectedReason = e.getRejectedMessage();
							break;
						}
					}
				}
			}
		}
		
		if( moveAllowed) {
			setHex(hexagon);
		}
		else {
			if(rejectedReason == null) {
				rejectedReason = "Move disallowed.";
			}
			fireMoveRejected(rejectedReason);
		}
	}

	public void addMoveEvaluator(IMoveEvaluator evaluator) {
		mMoveEvaluator.add(evaluator);
		evaluator.onAddEvaluator(this);
	}

	public List<IMoveEvaluator> getMoveEvaluators() 
	{
		List<IMoveEvaluator> evaluators = new ArrayList<IMoveEvaluator>(mMoveEvaluator);
		return evaluators;
	}
	
	private List<IMoveRejectedEventListener> mMoveRejectedListeners = new ArrayList<IMoveRejectedEventListener>(); 
	
	public void addMoveRejectedListener(IMoveRejectedEventListener listener) {
		mMoveRejectedListeners.add(listener);
	}
	
	public void removeMoveRejectedListener(IMoveRejectedEventListener listener) {
		mMoveRejectedListeners.remove(listener);
	}
	
	public void fireMoveRejected(String rejectedMessage) {
		MoveRejectedEvent event = new MoveRejectedEvent(this, rejectedMessage);
		for(IMoveRejectedEventListener listener : mMoveRejectedListeners) {
			listener.moveRejected(event);
		}
	}
	
	
	
}
